home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / 3dshade.exe / 3DSHADE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-22  |  22.2 KB  |  575 lines

  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <malloc.h>
  4. #include <graph.h>
  5. #include <process.h>
  6. #include <stdlib.h>
  7. #include <conio.h>
  8.  
  9. #define TRUE -1
  10. #define FALSE 0
  11.  
  12. static double f(double,double);
  13.        void   main(void);
  14.  
  15. void main()
  16.   {
  17.     static double aspect_ratio;
  18.     static double box_delta_x;
  19.     static double box_delta_y;
  20.     static int    box_num_1;
  21.     static int    box_num_2;
  22.     static int    box_x [4];
  23.     static double box_x_intercept;
  24.     static int    box_x1;
  25.     static int    box_x2;
  26.     static int    box_y [4];
  27.     static int    box_y_max;
  28.     static int    box_y_min;
  29.     static double box_y_offset;
  30.     static int    box_y1;
  31.     static short  color;
  32.     static double cos_rotation;
  33.     static double cos_tilt;
  34.     static double delta_x;
  35.     static double delta_y;
  36.     static double delta_z;
  37.     static int    finished;
  38.     static int    intercept_count_mod_2;
  39.     static int    key_index_1;
  40.     static int    key_index_2;
  41.     static int    line_x1;
  42.     static int    line_x2;
  43.     static int    line_y1;
  44.     static int    line_y2;
  45.     static double magnitude_normal;
  46.     static int    max_y_out;
  47.     static int    max_z_out;
  48.     static double normal_x;
  49.     static double normal_y;
  50.     static double normal_z;
  51.     static double num_bytes;
  52.     static int    num_x_divisions;
  53.     static int    num_x_primes;
  54.     static int    num_y_divisions;
  55.     static double pixels_per_unit;
  56.     static int    prime_num;
  57.     static double radians;
  58.     static double radians_per_degree;
  59.     static int    response;
  60.     static double rotation;
  61.     static double sin_rotation;
  62.     static double sin_tilt;
  63.     static int    sort_left;
  64.     static int    sort_right;
  65.     static double sort_t1;
  66.     static int    sort_t2;
  67.     static int    sort_t3;
  68.     static double tilt;
  69.     static long   tint;
  70.     static long   tint_increment;
  71.     static double x;
  72.     static int    *x_division_index;
  73.     static int    x_division_num;
  74.     static double x_eye;
  75.     static double x_max;
  76.     static double x_min;
  77.     static double *x_prime;
  78.     static double *x_prime_sorted;
  79.     static double x_prime_max;
  80.     static int    x_prime_num;
  81.     static double x_rotated;
  82.     static double x0;
  83.     static double x1;
  84.     static double x2;
  85.     static double x3;
  86.     static double y;
  87.     static double y_center;
  88.     static int    *y_division_index;
  89.     static int    y_division_num;
  90.     static double y_max;
  91.     static double y_min;
  92.     static double y_offset;
  93.     static double y_out_max;
  94.     static double *y_prime;
  95.     static double y_prime_max;
  96.     static double y_prime_min;
  97.     static double y0;
  98.     static double y1;
  99.     static double y2;
  100.     static double y3;
  101.     static double z;
  102.     static double z_center;
  103.     static double z_offset;
  104.     static double z_out_max;
  105.     static double *z_prime;
  106.     static double z_prime_max;
  107.     static double z_prime_min;
  108.     static double z0;
  109.     static double z1;
  110.     static double z2;
  111.     static double z3;
  112.  
  113.     max_y_out=319;
  114.     max_z_out=199;
  115.     printf("                             Three Dimensional Plot\n\n\n\n");
  116.     printf("Smallest value for x?  "); fflush(stdout);
  117.     scanf("%lf",&x_min);
  118.     printf("Largest value for x?  "); fflush(stdout);
  119.     scanf("%lf",&x_max);
  120.     printf("Smallest value for y?  "); fflush(stdout);
  121.     scanf("%lf",&y_min);
  122.     printf("Largest value for y?  "); fflush(stdout);
  123.     scanf("%lf",&y_max);
  124.     do
  125.       {
  126.         do
  127.           {
  128.             printf("Number of divisions for x?  "); fflush(stdout);
  129.             scanf("%d",&num_x_divisions);
  130.             if (num_x_divisions <= 1)
  131.               printf("? there must be at least 2 divisions\n");
  132.           }
  133.         while (num_x_divisions <= 1);
  134.         do
  135.           {
  136.             printf("Number of divisions for y?  "); fflush(stdout);
  137.             scanf("%d",&num_y_divisions);
  138.             if (num_y_divisions <= 1)
  139.               printf("? there must be at least 2 divisions\n");
  140.           }
  141.         while (num_y_divisions <= 1);
  142.         num_bytes=(float) num_x_divisions;
  143.         num_bytes*=((float) num_y_divisions);
  144.         num_bytes*=((float) sizeof(double));
  145.         if (num_bytes > 65536.0)
  146.           printf("? too many cells\n"); /* Oh, for a 32 bit compiler! */
  147.       }
  148.     while (num_bytes > 65536.0);
  149.     if ((x_prime
  150.      =(double *) malloc(num_x_divisions*num_y_divisions*sizeof(double)))
  151.      == NULL)
  152.       {
  153.         printf("Fatal error:  out of memory\n");
  154.         exit(4);
  155.       }
  156.     if ((x_prime_sorted
  157.      =(double *) malloc(num_x_divisions*num_y_divisions*sizeof(double)))
  158.      == NULL)
  159.       {
  160.         printf("Fatal error:  out of memory\n");
  161.         exit(4);
  162.       }
  163.     if ((y_prime
  164.      =(double *) malloc(num_x_divisions*num_y_divisions*sizeof(double)))
  165.      == NULL)
  166.       {
  167.         printf("Fatal error:  out of memory\n");
  168.         exit(4);
  169.       }
  170.     if ((z_prime
  171.      =(double *) malloc(num_x_divisions*num_y_divisions*sizeof(double)))
  172.      == NULL)
  173.       {
  174.         printf("Fatal error:  out of memory\n");
  175.         exit(4);
  176.       }
  177.     if ((x_division_index
  178.      =(int *) malloc(num_x_divisions*num_y_divisions*sizeof(int)))
  179.      == NULL)
  180.       {
  181.         printf("Fatal error:  out of memory\n");
  182.         exit(4);
  183.       }
  184.     if ((y_division_index
  185.      =(int *) malloc(num_x_divisions*num_y_divisions*sizeof(int)))
  186.      == NULL)
  187.       {
  188.         printf("Fatal error:  out of memory\n");
  189.         exit(4);
  190.       }
  191.     do
  192.       {
  193.         printf("Rotation about the z-axis (degrees)?  "); fflush(stdout);
  194.         scanf("%lf",&rotation);
  195.         printf("Tilt about the resulting y-axis (degrees)?  "); fflush(stdout);
  196.         scanf("%lf",&tilt);
  197.         printf("After the plot is displayed, press a key to continue.\n");
  198.         printf("Evaluating function...\n");
  199.         radians_per_degree=atan(1.0)/45.0;
  200.         radians=tilt*radians_per_degree;
  201.         cos_tilt=cos(radians);
  202.         sin_tilt=sin(radians);
  203.         radians=rotation*radians_per_degree;
  204.         cos_rotation=cos(radians);
  205.         sin_rotation=sin(radians);
  206.         z=f(x_min,y_min);
  207.         x_rotated=x_min*cos_rotation+y_min*sin_rotation;
  208.         y_prime_min=-x_min*sin_rotation+y_min*cos_rotation;
  209.         z_prime_min=-x_rotated*sin_tilt+z*cos_tilt;
  210.         y_prime_max=y_prime_min;
  211.         z_prime_max=z_prime_min;
  212.         x_prime_max=x_rotated*cos_tilt+z*sin_tilt;
  213.         delta_x=(double) num_x_divisions;
  214.         delta_x=(x_max-x_min)/delta_x;
  215.         delta_y=(double) num_y_divisions;
  216.         delta_y=(y_max-y_min)/delta_y;
  217.         x=x_min;
  218.         num_x_primes=0;
  219.         for (x_division_num=0; x_division_num < num_x_divisions;
  220.          x_division_num++)
  221.           {
  222.             y=y_min;
  223.             for (y_division_num=0; y_division_num < num_y_divisions;
  224.              y_division_num++)
  225.               {
  226.                 z=f(x,y);
  227.                 x_division_index[num_x_primes]=x_division_num;
  228.                 y_division_index[num_x_primes]=y_division_num;
  229.                 x_rotated=x*cos_rotation+y*sin_rotation;
  230.                 y_prime[num_x_primes]=-x*sin_rotation+y*cos_rotation;
  231.                 x_prime[num_x_primes]=x_rotated*cos_tilt+z*sin_tilt;
  232.                 z_prime[num_x_primes]=-x_rotated*sin_tilt+z*cos_tilt;
  233.                 if (x_prime[num_x_primes] > x_prime_max)
  234.                   x_prime_max=x_prime[num_x_primes];
  235.                 if (y_prime[num_x_primes] < y_prime_min)
  236.                   y_prime_min=y_prime[num_x_primes];
  237.                 if (y_prime[num_x_primes] > y_prime_max) 
  238.                   y_prime_max=y_prime[num_x_primes];
  239.                 if (z_prime[num_x_primes] < z_prime_min)
  240.                   z_prime_min=z_prime[num_x_primes];
  241.                 if (z_prime[num_x_primes] > z_prime_max)
  242.                   z_prime_max=z_prime[num_x_primes];
  243.                 y+=delta_y;
  244.                 num_x_primes++;
  245.               } 
  246.             x+=delta_x;
  247.           }
  248.         printf("Adjusting perspective...\n");
  249.         if ((y_prime_max-y_prime_min) > (z_prime_max-z_prime_min))
  250.           x_eye=2.0*(y_prime_max-y_prime_min)+x_prime_max;
  251.         else
  252.           x_eye=2.0*(z_prime_max-z_prime_min)+x_prime_max;
  253.         if (((y_prime_max-y_prime_min) > (z_prime_max-z_prime_min))
  254.         ||  (z_prime_max != z_prime_min))
  255.           {
  256.             y_center=(y_prime_max+y_prime_min)/2.0;
  257.             z_center=(z_prime_max+z_prime_min)/2.0;
  258.             num_x_primes=0;
  259.             for (x_division_num=0; x_division_num < num_x_divisions;
  260.              x_division_num++)
  261.               {
  262.                 y=y_min;
  263.                 for (y_division_num=0; y_division_num < num_y_divisions;
  264.                  y_division_num++)
  265.                   {
  266.                     x=x_prime[num_x_primes];
  267.                     y=y_prime[num_x_primes];
  268.                     z=z_prime[num_x_primes];
  269.                     delta_x=x-x_eye;
  270.                     delta_y=y-y_center;
  271.                     delta_z=z-z_center;
  272.                     x_prime[num_x_primes]
  273.                      =sqrt(delta_x*delta_x+delta_y*delta_y+delta_z*delta_z);
  274.                     y_prime[num_x_primes]
  275.                      =y_center+(y-y_center)*(x_eye-x_prime_max)/(x_eye-x);
  276.                     z_prime[num_x_primes]
  277.                      =z_center+(z-z_center)*(x_eye-x_prime_max)/(x_eye-x);
  278.                     num_x_primes++;
  279.                   }
  280.               }
  281.            }
  282.         for (x_prime_num=0; x_prime_num < num_x_primes; x_prime_num++)
  283.           x_prime_sorted[x_prime_num]=x_prime[x_prime_num];
  284.         printf("Sorting points...\n");
  285.         sort_left=num_x_primes/2;
  286.         sort_right=num_x_primes-1;
  287.         sort_t1=x_prime_sorted[0];
  288.         sort_t2=x_division_index[0];
  289.         sort_t3=y_division_index[0];
  290.         while (sort_right > 0)
  291.           { 
  292.             if (sort_left > 0)
  293.               {
  294.                 sort_left--;
  295.                 sort_t1=x_prime_sorted[sort_left];
  296.                 sort_t2=x_division_index[sort_left];
  297.                 sort_t3=y_division_index[sort_left];
  298.               }
  299.             else
  300.               {
  301.                 sort_t1=x_prime_sorted[sort_right];
  302.                 sort_t2=x_division_index[sort_right];
  303.                 sort_t3=y_division_index[sort_right];
  304.                 x_prime_sorted[sort_right]=x_prime_sorted[0];
  305.                 x_division_index[sort_right]=x_division_index[0];
  306.                 y_division_index[sort_right]=y_division_index[0];
  307.                 sort_right--;
  308.               }
  309.             if (sort_right > 0)
  310.               {
  311.                 finished=FALSE;
  312.                 key_index_2=sort_left;
  313.                 while (! finished)
  314.                   {
  315.                     key_index_1=key_index_2;
  316.                     key_index_2=2*key_index_2+1;
  317.                     if (key_index_2 > sort_right)
  318.                       finished=TRUE;
  319.                     else
  320.                       {
  321.                         if (key_index_2 != sort_right)
  322.                           {
  323.                             if (x_prime_sorted[key_index_2]
  324.                              > x_prime_sorted[key_index_2+1])
  325.                               key_index_2++;
  326.                           }
  327.                         if (sort_t1 <= x_prime_sorted[key_index_2])
  328.                           finished=TRUE;
  329.                         else
  330.                           {
  331.                             x_prime_sorted[key_index_1]
  332.                              =x_prime_sorted[key_index_2];
  333.                             x_division_index[key_index_1]
  334.                              =x_division_index[key_index_2];
  335.                             y_division_index[key_index_1]
  336.                              =y_division_index[key_index_2];
  337.                           }
  338.                       }
  339.                   }
  340.                 x_prime_sorted[key_index_1]=sort_t1;
  341.                 x_division_index[key_index_1]=sort_t2;
  342.                 y_division_index[key_index_1]=sort_t3;
  343.               }
  344.           } 
  345.         x_prime_sorted[0]=sort_t1;
  346.         x_division_index[0]=sort_t2;
  347.         y_division_index[0]=sort_t3;
  348.         _setvideomode(_MRES256COLOR);
  349.         tint=0l;
  350.         tint_increment=0x010101;
  351.         for (color=0; color < 64; color++)
  352.           {
  353.             _remappalette(color,tint);
  354.             tint+=tint_increment;
  355.           }
  356.         aspect_ratio=1.0/(4.0*(200.0/320.0)/3.0);
  357.         y_out_max=(double) max_y_out;
  358.         z_out_max=(double) max_z_out;
  359.         if (aspect_ratio*z_out_max*(y_prime_max-y_prime_min)
  360.          > y_out_max*(z_prime_max-z_prime_min))
  361.           {
  362.             pixels_per_unit=y_out_max/(aspect_ratio*(y_prime_max-y_prime_min));
  363.             y_offset=0.0;
  364.             z_offset=-(z_out_max-pixels_per_unit*(z_prime_max-z_prime_min))/2.0;
  365.           }
  366.         else
  367.           if (aspect_ratio*z_out_max*(y_prime_max-y_prime_min)
  368.            < y_out_max*(z_prime_max-z_prime_min))
  369.             {
  370.               pixels_per_unit=z_out_max/(z_prime_max-z_prime_min);
  371.               y_offset=(y_out_max
  372.                -aspect_ratio*pixels_per_unit*(y_prime_max-y_prime_min))/2.0;
  373.               z_offset=0.0;
  374.             }
  375.           else
  376.             {
  377.               pixels_per_unit=1.0;
  378.               y_offset=y_out_max/2.0;
  379.               z_offset=-z_out_max/2.0;
  380.             }
  381.         for (x_prime_num=0; x_prime_num < num_x_primes; x_prime_num++)
  382.           {
  383.             x_division_num=x_division_index[x_prime_num];
  384.             if (x_division_num < (num_x_divisions-1))
  385.               {
  386.                 y_division_num=y_division_index[x_prime_num];
  387.                 if (y_division_num < (num_y_divisions-1))
  388.                   {  
  389.                     prime_num=num_y_divisions*x_division_num+y_division_num;
  390.                     x0=x_prime[prime_num];
  391.                     y0=y_prime[prime_num];
  392.                     z0=z_prime[prime_num];
  393.                     prime_num+=num_y_divisions;
  394.                     x1=x_prime[prime_num];
  395.                     y1=y_prime[prime_num];
  396.                     z1=z_prime[prime_num];
  397.                     prime_num++;
  398.                     x2=x_prime[prime_num];
  399.                     y2=y_prime[prime_num];
  400.                     z2=z_prime[prime_num];
  401.                     prime_num-=num_y_divisions;
  402.                     x3=x_prime[prime_num];
  403.                     y3=y_prime[prime_num];
  404.                     z3=z_prime[prime_num];
  405.                     box_x[0]=(int) (y_offset
  406.                      +pixels_per_unit*aspect_ratio*(y0-y_prime_min));
  407.                     box_y[0]=(int) (z_offset+z_out_max
  408.                      -pixels_per_unit*(z0-z_prime_min));
  409.                     box_x[1]=(int) (y_offset
  410.                      +pixels_per_unit*aspect_ratio*(y1-y_prime_min));
  411.                     box_y[1]=(int) (z_offset+z_out_max
  412.                      -pixels_per_unit*(z1-z_prime_min));
  413.                     box_x[2]=(int) (y_offset
  414.                      +pixels_per_unit*aspect_ratio*(y2-y_prime_min));
  415.                     box_y[2]=(int) (z_offset+z_out_max
  416.                      -pixels_per_unit*(z2-z_prime_min));
  417.                     box_x[3]=(int) (y_offset
  418.                      +pixels_per_unit*aspect_ratio*(y3-y_prime_min));
  419.                     box_y[3]=(int) (z_offset+z_out_max
  420.                      -pixels_per_unit*(z3-z_prime_min));
  421.                     box_y_min=box_y[0];
  422.                     box_y_max=box_y_min;
  423.                     normal_x=(y1-y0)*(z3-z0)-(y3-y0)*(z1-z0);
  424.                     normal_y=(x3-x0)*(z1-z0)-(x1-x0)*(z3-z0);
  425.                     normal_z=(x1-x0)*(y3-y0)-(x3-x0)*(y1-y0);
  426.                     magnitude_normal=sqrt(
  427.                      normal_x*normal_x+normal_y*normal_y+normal_z*normal_z);
  428.                     if (magnitude_normal == 0.0)
  429.                       color=(short) 0;
  430.                     else
  431.                       {
  432.                         color=(short) (64.0*fabs(normal_x)/magnitude_normal);
  433.                         if (color == (short) 64)
  434.                           color=(short) 63;
  435.                       }
  436.                     for (box_num_1=1; box_num_1 < 4; box_num_1++)
  437.                       {
  438.                         if (box_y[box_num_1] < box_y_min)
  439.                           box_y_min=box_y[box_num_1];
  440.                         if (box_y[box_num_1] > box_y_max)
  441.                           box_y_max=box_y[box_num_1];
  442.                       }
  443.                     for (box_y1=box_y_min; box_y1 <= box_y_max; ++box_y1)
  444.                       {
  445.                         intercept_count_mod_2=0;
  446.                         box_num_2=1;
  447.                         for (box_num_1=0; box_num_1 < 4; ++box_num_1)
  448.                           {
  449.                             if (box_y[box_num_1] >= box_y1)
  450.                               {
  451.                                 if (box_y1 > box_y[box_num_2])
  452.                                   {
  453.                                     box_delta_y=(double)
  454.                                      (box_y[box_num_2]-box_y[box_num_1]);
  455.                                     box_delta_x=(double)
  456.                                      (box_x[box_num_2]-box_x[box_num_1]);
  457.                                     box_y_offset=(double)
  458.                                      (box_y1-box_y[box_num_1]);
  459.                                     box_x_intercept=(double) (box_x[box_num_1]);
  460.                                     box_x1=(int) ((box_delta_x*box_y_offset)
  461.                                      /box_delta_y+box_x_intercept);
  462.                                     if (intercept_count_mod_2 == 0)
  463.                                       box_x2=box_x1;
  464.                                     else
  465.                                       {
  466.                                         if (box_x1 < box_x2)
  467.                                           {
  468.                                             line_x1=box_x1;
  469.                                             line_x2=box_x2;
  470.                                           }
  471.                                         else
  472.                                           {
  473.                                             line_x1=box_x2;
  474.                                             line_x2=box_x1;
  475.                                           }
  476.                                         _setcolor(color);
  477.                                         _setpixel(line_x1,box_y1);
  478.                                         while (line_x1 < line_x2)
  479.                                           {
  480.                                             line_x1++;
  481.                                             _setpixel(line_x1,box_y1);
  482.                                           }
  483.                                       }
  484.                                     intercept_count_mod_2=1-intercept_count_mod_2;
  485.                                   }
  486.                               }
  487.                             else
  488.                               {
  489.                                 if (box_y1 <= box_y[box_num_2])
  490.                                   {
  491.                                     box_delta_y=(double)
  492.                                      (box_y[box_num_2]-box_y[box_num_1]);
  493.                                     box_delta_x=(double)
  494.                                      (box_x[box_num_2]-box_x[box_num_1]);
  495.                                     box_y_offset=(double)
  496.                                      (box_y1-box_y[box_num_1]);
  497.                                     box_x_intercept=(double) (box_x[box_num_1]);
  498.                                     box_x1=(int) ((box_delta_x*box_y_offset)
  499.                                      /box_delta_y+box_x_intercept);
  500.                                     if (intercept_count_mod_2 == 0)
  501.                                       box_x2=box_x1;
  502.                                     else
  503.                                       {
  504.                                         if (box_x1 < box_x2)
  505.                                           {
  506.                                             line_x1=box_x1;
  507.                                             line_x2=box_x2;
  508.                                           }
  509.                                         else
  510.                                           {
  511.                                             line_x1=box_x2;
  512.                                             line_x2=box_x1;
  513.                                           }
  514.                                         _setcolor(color);
  515.                                         _setpixel(line_x1,box_y1);
  516.                                         while (line_x1 < line_x2)
  517.                                           {
  518.                                             line_x1++;
  519.                                             _setpixel(line_x1,box_y1);
  520.                                           }
  521.                                       }
  522.                                     intercept_count_mod_2=1-intercept_count_mod_2;
  523.                                   }
  524.                               }
  525.                             box_num_2++;
  526.                             if (box_num_2 >= 4)
  527.                               box_num_2=0;
  528.                           }
  529.                       }
  530.                     box_num_2=1;
  531.                     for (box_num_1=0; box_num_1 < 4; ++box_num_1)
  532.                       {
  533.                         line_x1=box_x[box_num_1];
  534.                         line_y1=box_y[box_num_1];
  535.                         line_x2=box_x[box_num_2];
  536.                         line_y2=box_y[box_num_2];
  537.                         box_num_2++;
  538.                         _setcolor(color);
  539.                         _moveto(line_x1,line_y1);
  540.                         _lineto(line_x2,line_y2);
  541.                         if (box_num_2 >= 4)
  542.                           box_num_2=0;
  543.                       }
  544.                   }
  545.               }
  546.           }
  547.         fflush(stdin);
  548.         response=getch();
  549.         fflush(stdin);
  550.         _setvideomode(_DEFAULTMODE);
  551.         printf("                             Three Dimensional Plot\n\n\n\n");
  552.         printf("Again (y or n)?  ");
  553.         response=getche();
  554.         printf("\n");
  555.       }
  556.     while ((response == ((int) 'Y')) || (response == ((int) 'y')));
  557.     free((void *) y_division_index);
  558.     free((void *) x_division_index);
  559.     free((void *) z_prime);
  560.     free((void *) y_prime);
  561.     free((void *) x_prime);
  562.   }
  563.  
  564. static double f(x,y)
  565.   double x;
  566.   double y;
  567.     {
  568.       static double t1;
  569.       static double t2;
  570.  
  571.       t1=x*x+y*y;
  572.       t2=cos(7.0*sqrt(t1));
  573.       return(2*t2*t2/(1.0+30.0*t1));
  574.     }
  575.